//
// Created by hoyin on 2022/3/15.
//

#ifndef AUST_RM_VISION_2022_FILTER_H
#define AUST_RM_VISION_2022_FILTER_H

#include "iostream"

using namespace std;
using namespace cv;
using namespace mu;

class Filter {
private:
//	采样数
	unsigned int N = 0;
//	滤波器游标
	unsigned int flag = 0;

	static vector<string> split(const string &s, const string &seperator){
		vector<string> result;
		typedef string::size_type string_size;
		string_size i = 0;

		while(i != s.size()){
			//找到字符串中首个不等于分隔符的字母；
			int flag = 0;
			while(i != s.size() && flag == 0){
				flag = 1;
				for(char x : seperator)
					if(s[i] == x){
						++i;
						flag = 0;
						break;
					}
			}

			//找到又一个分隔符，将两个分隔符之间的字符串取出；
			flag = 0;
			string_size j = i;
			while(j != s.size() && flag == 0){
				for(char x : seperator)
					if(s[j] == x){
						flag = 1;
						break;
					}
				if(flag == 0)
					++j;
			}
			if(i != j){
				result.push_back(s.substr(i, j-i));
				i = j;
			}
		}
		return result;
	}

public:
	explicit Filter(unsigned int N) {
		setCapacity(N);
	}

	void updateFlag() {
		flag++;
	}

	unsigned int getFlag() const {
		return flag;
	}

	void setCapacity(unsigned int samplingCapacity) {
		N = samplingCapacity;
	}

	unsigned int getCapacity() const {
		return N;
	}

	bool readyToFilter() const {
		return flag % N == 0 && flag > N;
	}

	static double medianFilter(vector<double>& data, unsigned int start, unsigned int end) {
		vector<double> subVec;
		subVec.reserve(end - start);
		for (unsigned int i = start; i < end; ++i) {
			subVec.push_back(data.at(i));
		}
		sort(subVec.begin(), subVec.end());
		unsigned int mid = (int) (end - start)/2;
		return subVec.at(mid);
	}

	static double medianAverageFilter(vector<double> &data, unsigned int start, unsigned int end) {
		vector<double> subVec;
		subVec.reserve(end - start);
		for (unsigned int i = start; i < end; ++i) {
			subVec.push_back(data.at(i));
		}
		sort(subVec.begin(), subVec.end());
		double sum = 0;
		for (int i = 1; i < end - start - 1; ++i) {
			sum += subVec.at(i);
		}
		return sum / (end - start);
	}

	static vector<vector<double>> classifyFilter(vector<vector<double>> &data, unsigned int start, unsigned int end, double threshMin=0, double threshMax=0) {
		vector<vector<double>> c1, c2;
		vector<double> distAvg;
		double globalDistMean;

		for (unsigned int i = start; i < end; ++i) {
			vector<double> dist;
			for (unsigned int j = start; j < end; ++j) {
				if (j == i) continue;
				if (threshMin != threshMax) {
					if (data.at(i)[1] > threshMax || data.at(i)[1] < threshMin) {
						continue;
					}
				}
				dist.push_back(abs(data.at(i)[1] - data.at(j)[1]));
//				dist.push_back(pow(data.at(i)[1] - data.at(j)[1], 2));
			}
			distAvg.push_back(average(dist));
		}

		globalDistMean = average(distAvg);
		for (unsigned int i = start; i < end; ++i) {
			if (threshMin != threshMax) {
				if (data.at(i)[1] > threshMax || data.at(i)[1] < threshMin) {
					continue;
				}
			}
			if (distAvg[i - start] < globalDistMean) {
				c1.push_back(data.at(i));
			} else {
				c2.push_back(data.at(i));
			}
		}

		if (c1.size() > c2.size()) {
			return c1;
		} else {
			return c2;
		}
	}

	static vector<double> classifyFilter(vector<double> &data, unsigned int start, unsigned int end) {
		vector<double> c1, c2;
		vector<double> distAvg;
		double globalDistMean = 0;

		for (unsigned int i = start; i < end; ++i) {
			vector<double> dist;
			for (unsigned int j = start; j < end; ++j) {
				if (j == i) continue;
				dist.push_back(abs(data[i] - data[j]));
			}
			distAvg.push_back(average(dist));
		}

		globalDistMean = average(distAvg);
		for (unsigned int i = start; i < end; ++i) {
			if (distAvg[i - start] < globalDistMean) {
				c1.push_back(data.at(i));
			} else {
				c2.push_back(data.at(i));
			}
		}

		if (c1.size() > c2.size()) {
			return c1;
		} else {
			return c2;
		}
	}
};

#endif //AUST_RM_VISION_2022_FILTER_H
